package com.gitee.l0km.aocache;

/**
 * 管理线程局部上下文
 */
public class ContextHolder {
	static final ThreadLocal<AocacheContext> CONTEXT = new ThreadLocal<>();

	/**
	 * 获取线程局部上下文中的返回值安全策略。
	 * <p>
	 * 如果上下文中未设置返回值安全策略，则返回传入的默认值。
	 * </p>
	 * 
	 * @param defaultValue 当上下文中未设置返回值安全策略时返回的默认值
	 * @return 线程局部上下文中的返回值安全策略，如果未设置则返回默认值
	 */
	static SafeStrategy getReturnSafeStrategy(SafeStrategy defaultValue) {
		AocacheContext context = CONTEXT.get();
		SafeStrategy strategy;
		if (null == context || null == (strategy = context.returnSafeStrategy)) {
			return defaultValue;
		}
		return strategy;
	}
	/**
	 * <p>
	 * 将当前线程局部上下文中的 {@link AocacheContext#computeInvocation} 标志设置为 {@code true}，
	 * 表示当前调用是计算调用。如果上下文中不存在，则不进行任何操作。
	 * </p>
	 */
	static void computeInvocation() {
		AocacheContext context = CONTEXT.get();
		if (null != context) {
			context.computeInvocation = true;
		}
	}
    /**
	 * <p>检查传入的 {@link AocacheContext} 实例是否需要手动清除上下文。</p><br>
	 * <p>如果传入的上下文实例为 {@code null}，则返回 {@code false}；</p><br>
	 * <p>否则返回该实例的 {@code manualClean} 标志值。</p>
	 * 
	 * @param context 要检查的 {@link AocacheContext} 实例
	 * @return 如果需要手动清除上下文则返回 {@code true}，否则返回 {@code false}
	 */
	static boolean isManualClean(AocacheContext context) {
    	return null == context ? false : context.manualClean;
    }
	/**
	 * <p>检查传入的 {@link AocacheContext} 实例是否为刷新缓存调用。</p><br>
	 * <p>如果传入的上下文实例为 {@code null}，则返回 {@code false}；</p><br>
	 * <p>否则返回该实例的 {@code refreshInvocation} 标志值。</p>
	 * 
	 * @param context 要检查的 {@link AocacheContext} 实例
	 * @return 如果是刷新缓存调用则返回 {@code true}，否则返回 {@code false}
	 */
	static boolean isRefreshInvocation(AocacheContext context) {
		return null == context ? false : context.refreshInvocation;
	}
    /**
     * 获取当前线程的局部上下文。
     * <p>
     * 如果当前线程的局部上下文中没有存储上下文信息，则会创建一个新的上下文实例并存储到线程局部变量中。
     * </p>
     * 
     * @return 当前线程的局部上下文实例
     */
    public static AocacheContext getLocalContext() {
		AocacheContext context = CONTEXT.get();
		if (context == null) {
			context = new AocacheContext();
			CONTEXT.set(context);
		}
		return context;
	}
    /**
     * 清除当前线程的局部上下文。
     * <p>
     * 该方法会移除存储在线程局部变量中的上下文信息，确保在不需要上下文时释放资源。
     * </p>
     */
    public static void clearLocalContext() {
		CONTEXT.remove();
	}

	/**
	 * 线程局部上下文的内部类。<br>
	 */
	public static class AocacheContext {
		/**
		 * 线程局部上下文中的返回值安全策略。
		 */
		private SafeStrategy returnSafeStrategy;
		/**
		 * 指示是否手动清除上下文的标志。
		 * <p>
		 * 如果该标志为 {@code true}，则为应用层负责手动调用清除方法；否则方法调用结束会自动清除。
		 * </p>
		 */
		private boolean manualClean;
		/**
		 * 标记当前调用是否为计算调用。
		 * <p>
		 * 如果该标志为 {@code true}，则为计算调用；否则为获取缓存命中调用。
		 * </p>
		 */
		private boolean computeInvocation;
		/**
		 * 标记当前调用是否为刷新缓存调用。
		 * <p>
		 * 如果该标志为 {@code true}，则为刷新缓存；否则为普通调用。
		 * </p>
		 */
		private boolean refreshInvocation;
		/**
		 * 私有构造函数，确保只能在类内部创建实例。
		 */
		private AocacheContext() {
		}

		/**
		 * 设置线程局部上下文中的返回值安全策略。
		 * 
		 * @param returnSafeStrategy 要设置的返回值安全策略
		 * @return 当前上下文实例，支持链式调用
		 */
		public AocacheContext returnSafeStrategy(SafeStrategy returnSafeStrategy) {
			this.returnSafeStrategy = returnSafeStrategy;
			return this;
		}

		/**
		 * 设置是否需要手动清除上下文的标志。默认情况下为 {@code false}。
		 * 
		 * @param manualClean 如果需要手动清除则设置为 {@code true}，否则设置为 {@code false}
		 * @return 当前上下文实例，支持链式调用
		 */
		public AocacheContext manualClean(boolean manualClean) {
			this.manualClean = manualClean;
			return this;
		}

		/**
		 * 用于应用层检查最近一次调用是否为计算调用。
		 * @return 如果是计算调用则返回 {@code true}，否则返回 {@code false}
		 */
		public boolean isComputeInvocation() {
			return computeInvocation;
		}

	/**
	 * <p>设置当前调用是否为刷新缓存调用。</p>
	 * <p>如果传入参数为 {@code true}，则表示当前调用为刷新缓存调用；否则为普通调用。</p>
	 * 
	 * @param refreshInvocation 用于标记是否为刷新缓存调用的布尔值
	 */
	public void setRefreshInvocation(boolean refreshInvocation) {
			this.refreshInvocation = refreshInvocation;
		}
	}
}